# newProject/chart/chart_generator.py
import os
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.figure import Figure
from matplotlib.backends.backend_qtagg import FigureCanvasQTAgg


# 设置matplotlib字体
plt.rcParams['font.sans-serif'] = ['SimHei'] # 使用黑体
plt.rcParams['axes.unicode_minus'] = False # 解决负号显示问题

class ChartGenerator:
    @staticmethod
    def create_figure(parent=None):
        """创建Matplotlib画布"""
        fig = Figure(figsize=(8, 6), dpi=100)
        canvas = FigureCanvasQTAgg(fig)
        return fig, canvas

    @classmethod
    def generate_chart(cls, folder_path, chart_type, data_type):
        """生成图表主方法"""
        try:
            # 读取数据
            df = cls._read_data(folder_path, data_type)
            
            # 创建图表
            fig, canvas = cls.create_figure()
            ax = fig.add_subplot(111)
            
            # 根据类型生成不同图表
            if chart_type == "柱状图":
                df.plot(kind='bar', ax=ax)
            elif chart_type == "饼状图":
                df.plot(kind='pie', ax=ax, y=df.columns[0])
            elif chart_type == "折线图":
                df.plot(kind='line', ax=ax)
            else:
                raise ValueError("不支持的图表类型")
            
            ax.set_title("数据分析图表")

            # 动态调整x轴标签
            adjust_x_axis_labels(ax, df)

            fig.tight_layout()
            return canvas
        except Exception as e:
            raise RuntimeError(f"图表生成失败: {str(e)}")
        
    @classmethod
    def generate_chart_from_df(cls, df, chart_type, data_type):
        """从DataFrame生成图表"""
        try:
            # 创建图表
            fig, canvas = cls.create_figure()
            ax = fig.add_subplot(111)
            
            # 根据类型生成不同图表
            if chart_type == "柱状图":
                df.plot(kind='bar', ax=ax)
            elif chart_type == "饼状图":
                # 饼状图特殊处理
                if not df.empty and not df.columns[0] in df.columns:
                    raise ValueError("数据格式不正确")
                df[df.columns[0]].value_counts().plot(kind='pie', ax=ax, autopct='%1.1f%%')
            elif chart_type == "折线图":
                df.plot(kind='line', ax=ax)
            else:
                raise ValueError("不支持的图表类型")
            
            ax.set_title("数据分析图表")

            # 动态调整x轴标签（饼状图不需要）
            if chart_type != "饼状图":
                adjust_x_axis_labels(ax, df)

            # 禁用 tight_layout() 或手动调整布局
            plt.subplots_adjust(left=0.1, right=0.9, top=0.9, bottom=0.1)  # 手动调整布局

            return canvas
        except Exception as e:
            raise RuntimeError(f"图表生成失败: {str(e)}")
        
    @staticmethod
    def _read_data(folder_path, data_type):
        """读取文件夹中的数据文件"""
        valid_files = []
        for f in os.listdir(folder_path):
            if data_type == "CSV" and f.endswith(".csv"):
                valid_files.append(os.path.join(folder_path, f))
            elif data_type == "Excel" and f.endswith((".xls", ".xlsx")):
                valid_files.append(os.path.join(folder_path, f))
        
        if not valid_files:
            raise FileNotFoundError("未找到匹配的数据文件")
        
        # 读取第一个匹配的文件
        file_path = valid_files[0]
        if data_type == "CSV":
            return pd.read_csv(file_path)
        elif data_type == "Excel":
            return pd.read_excel(file_path)
        
def adjust_x_axis_labels(ax, df):
    n = len(df)
    if n <= 10:
        step = 1
    elif n <= 100:
        step = 10
    elif n <= 1000:
        step = 100
    else:
        step = 1000

    xticks = df.index[::step]
    ax.set_xticks(xticks)
    ax.set_xticklabels(xticks)
    plt.xticks(rotation=45)  # 旋转45度